package com.task.socket;

import com.alibaba.fastjson.JSON;
import com.task.config.MyEndpointConfigure;
import com.task.pojo.ChatContent;
import com.task.pojo.SocketModel;
import com.task.server.ChatRecordService;
import com.task.server.GroupUserService;
import com.task.util.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author jiafujun
 * 2020年01月09日 15:12:00
 */
@Slf4j
@Service
@ServerEndpoint(value = "/app",configurator= MyEndpointConfigure.class)
public class MyWebsocketServer {

    private static Map<String, Session> clients = new ConcurrentHashMap<>();

    @Autowired
    private GroupUserService groupUserService;
    @Autowired
    private ChatRecordService chatRecordService;

    @OnOpen
    public void onOpen(Session session) {
        log.info("有新的客户端连接了: {}", session.getId());
        Map<String, List<String>> paramete = session.getRequestParameterMap();

        //将新用户存入在线的组
        clients.put(paramete.get("id").get(0), session);

        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                SocketModel model = new SocketModel(session.getId(), null, "connect");
                session.getAsyncRemote().sendText(JSON.toJSONString(model));
            }
        };
        new Thread(runnable).start();

    }

    /**
     * 客户端关闭
     *
     * @param session session
     */
    @OnClose
    public void onClose(Session session) {
        log.info("有用户断开了, id为:{}", session.getId());
        //将掉线的用户移除在线的组里
        clients.remove(session.getId());
    }

    /**
     * 收到客户端发来消息
     *
     * @param message 消息对象
     */
    @OnMessage
    public void onMessage(String message) {
        try {
            SocketModel model = JSON.parseObject(message, SocketModel.class);
            //心跳不用管
            if (model.getContent().equals("heartbeat")) {
                log.info("心跳连接：" + message);
                return;
            }
            log.info("服务端收到客户端发来的消息: {}", message);

            //发送消息
            if (model.getTargetId() != null) {
                this.sendId(model, message);
            } else if (model.getGroupId() != null) {
                this.sendGroup(model, message);
            } else {
                this.sendAll(message);
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("处理消息失败：" + message);
        }
    }

    /**
     * 给当前在线的所有人发送消息
     *
     * @param message 消息内容
     */
    private void sendAll(String message) {
        for (Map.Entry<String, Session> sessionEntry : clients.entrySet()) {
            sessionEntry.getValue().getAsyncRemote().sendText(message);
        }
    }

    /**
     * 发送给全里的消息
     *
     * @param model
     * @param message
     */
    private void sendGroup(SocketModel model, String message) {
        List<String> users = groupUserService.getUsers(model.getGroupId());
        users.forEach(id -> {
            Session session = clients.get(id);
            if (session != null) {
                session.getAsyncRemote().sendText(message);
                //todo 保存聊天记录
            }
        });
    }

    /**
     * 指定发送给一个客户端
     *
     * @param model
     * @param message
     */
    private void sendId(SocketModel model, String message) {
        //给对方发送
        Session session = clients.get(model.getTargetId());
        if (session != null) {
            session.getAsyncRemote().sendText(message);

        }
        //给自己发送
        Session sess = clients.get(model.getId());
        sess.getAsyncRemote().sendText(message);
        //保存聊天记录
        ChatContent content = new ChatContent(Integer.valueOf(model.getId()), Integer.valueOf(model.getTargetId()),
                message, DateUtil.getStrToDate(model.getTime()));
        chatRecordService.save(content);
    }


}
